x86, hvm: Implement interrupt routing to least priority processor.
authorKeir Fraser <keir.fraser@citrix.com>
Tue, 18 Nov 2008 11:16:36 +0000 (11:16 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Tue, 18 Nov 2008 11:16:36 +0000 (11:16 +0000)
Instead of round robin the vcpu with the lowest processor
priority is selected for the interrupt. If multiple vcpus
share the same low priority then interrupts are distributed between
those round robin.

Signed-off-by: Juergen Gross <juergen.gross@fujitsu-siemens.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
xen/arch/x86/hvm/vioapic.c
xen/arch/x86/hvm/vlapic.c
xen/arch/x86/hvm/vmsi.c
xen/include/asm-x86/hvm/vlapic.h

index 7250de3a7d3961fc3f9dddc3543db40af8a85bf4..7f63699ab27e1893869dd2a8ea02c8bb6eb0c32b 100644 (file)
@@ -344,8 +344,8 @@ static void vioapic_deliver(struct hvm_hw_vioapic *vioapic, int irq)
         }
         else
 #endif
-            target = apic_round_robin(vioapic_domain(vioapic),
-                                      vector, deliver_bitmask);
+            target = apic_lowest_prio(vioapic_domain(vioapic),
+                                      deliver_bitmask);
         if ( target != NULL )
         {
             ioapic_inj_irq(vioapic, target, vector, trig_mode, delivery_mode);
index d201af28484ea88618aade721a253425fcbe4803..68e9b27632c01830ee89729cfa0f458b9b0b7f43 100644 (file)
@@ -377,26 +377,30 @@ static int vlapic_accept_irq(struct vcpu *v, int delivery_mode,
 }
 
 /* This function is used by both ioapic and lapic.The bitmap is for vcpu_id. */
-struct vlapic *apic_round_robin(
-    struct domain *d, uint8_t vector, uint32_t bitmap)
+struct vlapic *apic_lowest_prio(struct domain *d, uint32_t bitmap)
 {
-    int next, old;
-    struct vlapic *target = NULL;
+    int old = d->arch.hvm_domain.irq.round_robin_prev_vcpu;
+    uint32_t ppr, target_ppr = UINT_MAX;
+    struct vlapic *vlapic, *target = NULL;
+    struct vcpu *v;
 
-    old = next = d->arch.hvm_domain.irq.round_robin_prev_vcpu;
+    if ( unlikely((v = d->vcpu[old]) == NULL) )
+        return NULL;
 
     do {
-        if ( ++next == MAX_VIRT_CPUS ) 
-            next = 0;
-        if ( (d->vcpu[next] == NULL) || !test_bit(next, &bitmap) )
-            continue;
-        target = vcpu_vlapic(d->vcpu[next]);
-        if ( vlapic_enabled(target) )
-            break;
-        target = NULL;
-    } while ( next != old );
+        v = v->next_in_list ? : d->vcpu[0];
+        vlapic = vcpu_vlapic(v);
+        if ( test_bit(v->vcpu_id, &bitmap) && vlapic_enabled(vlapic) &&
+             ((ppr = vlapic_get_ppr(vlapic)) < target_ppr) )
+        {
+            target = vlapic;
+            target_ppr = ppr;
+        }
+    } while ( v->vcpu_id != old );
 
-    d->arch.hvm_domain.irq.round_robin_prev_vcpu = next;
+    if ( target != NULL )
+        d->arch.hvm_domain.irq.round_robin_prev_vcpu =
+            vlapic_vcpu(target)->vcpu_id;
 
     return target;
 }
@@ -456,7 +460,7 @@ int vlapic_ipi(
 
     if ( delivery_mode == APIC_DM_LOWEST )
     {
-        target = apic_round_robin(vlapic_domain(v), vector, lpr_map);
+        target = apic_lowest_prio(vlapic_domain(v), lpr_map);
         if ( target != NULL )
             rc = vlapic_accept_irq(vlapic_vcpu(target), delivery_mode,
                                    vector, level, trig_mode);
index 6eefb61bfa0da052bab036b56e3b650bf3dea907..cc9e9adde5f122ab0662a6c5cab5a0d155337a4e 100644 (file)
@@ -152,7 +152,7 @@ int vmsi_deliver(struct domain *d, int pirq)
     {
     case dest_LowestPrio:
     {
-        target = apic_round_robin(d, vector, deliver_bitmask);
+        target = apic_lowest_prio(d, deliver_bitmask);
         if ( target != NULL )
             vmsi_inj_irq(d, target, vector, trig_mode, delivery_mode);
         else
index 3f34e4795022664042e4bf6c0604dad0440e432e..8c36ed5a0092d11d0cd6d9cc1518e4309d15c7e9 100644 (file)
@@ -93,8 +93,7 @@ void vlapic_msr_set(struct vlapic *vlapic, uint64_t value);
 
 int vlapic_accept_pic_intr(struct vcpu *v);
 
-struct vlapic *apic_round_robin(
-    struct domain *d, uint8_t vector, uint32_t bitmap);
+struct vlapic *apic_lowest_prio(struct domain *d, uint32_t bitmap);
 
 int vlapic_match_logical_addr(struct vlapic *vlapic, uint8_t mda);